//
//  TaskViewController.m
//  iOS-Learning-Demo
//
//  Created by yuan xiaodong on 2022/1/4.
//  Copyright © 2022 yuan. All rights reserved.
//

#import "TaskViewController.h"
#import "BLAsyncBlockOperation.h"

static NSString *kQueueOperationsChanged = @"kQueueOperationsChanged";

@interface TaskViewController ()

@property (nonatomic, strong) NSOperationQueue *compressOperQueue; //压缩队列
@property (nonatomic, strong) NSOperationQueue *uploadOperQueue;   //上传队列

@property (nonatomic, strong) dispatch_semaphore_t compressSemaphore;
@property (nonatomic, strong) dispatch_semaphore_t uploadSemaphore;

@property (nonatomic, strong) NSOperationQueue *ongoingQueue; //进行中的任务
@property (nonatomic, strong) NSOperationQueue *blockingQueue; //排队中的任务

@end

@implementation TaskViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"任务队列";
    self.view.backgroundColor = UIColor_F8;
    
    UIButton *btn = UIButton.new;
    btn.backgroundColor = UIColorFromRGB(0x9B9B9B);
    [btn.titleLabel setFont:[UIFont boldSystemFontOfSize:16]];
    [btn setTitle:@"任务开始" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(startTask) forControlEvents:UIControlEventTouchUpInside];
    btn.layer.cornerRadius  = 6;
    btn.layer.masksToBounds = YES;
    btn.frame = CGRectMake(100, 100, 100, 50);
    
    UIButton *addBtn = UIButton.new;
    addBtn.backgroundColor = UIColorFromRGB(0x9B9B9B);
    [addBtn.titleLabel setFont:[UIFont boldSystemFontOfSize:16]];
    [addBtn setTitle:@"添加任务" forState:UIControlStateNormal];
    [addBtn addTarget:self action:@selector(addTask) forControlEvents:UIControlEventTouchUpInside];
    addBtn.frame = CGRectMake(btn.left, btn.bottom+20, btn.width, btn.height);
    
    UIButton *cancelBtn = UIButton.new;
    cancelBtn.backgroundColor = UIColorFromRGB(0x9B9B9B);
    [cancelBtn.titleLabel setFont:[UIFont boldSystemFontOfSize:16]];
    [cancelBtn setTitle:@"取消所有任务" forState:UIControlStateNormal];
    [cancelBtn addTarget:self action:@selector(cancelAllTask) forControlEvents:UIControlEventTouchUpInside];
    cancelBtn.frame = CGRectMake(btn.left, addBtn.bottom+20, btn.width, btn.height);
    
    [self.view addSubview:btn];
    [self.view addSubview:addBtn];
    [self.view addSubview:cancelBtn];
}

#pragma mark - *********** 压缩任务控制 ***********

- (NSOperationQueue *)compressOperQueue{
    if (!_compressOperQueue){
        _compressOperQueue = [[NSOperationQueue alloc]init];
        _compressOperQueue.maxConcurrentOperationCount = 1;
        [_compressOperQueue addObserver:self forKeyPath:@"operations" options:0 context:&kQueueOperationsChanged];
    }
    return _compressOperQueue;
}

- (dispatch_semaphore_t)compressSemaphore{
    if (!_compressSemaphore){
        _compressSemaphore = dispatch_semaphore_create(1);
    }
    return _compressSemaphore;
}

- (void)compressLock{
    dispatch_semaphore_wait(self.compressSemaphore, DISPATCH_TIME_FOREVER);
}

- (void)compressUnLock{
    dispatch_semaphore_signal(self.compressSemaphore);
}

#pragma mark - *********** 上传任务控制 ***********

- (NSOperationQueue *)ongoingQueue{
    if (!_ongoingQueue){
        _ongoingQueue = [[NSOperationQueue alloc]init];
        _ongoingQueue.maxConcurrentOperationCount = 1;
    }
    return _ongoingQueue;
}

//并发队列+异步任务+并发数控制
- (void)startTask{
    //DISPATCH_QUEUE_SERIAL
    dispatch_queue_t queue = dispatch_queue_create("taskQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        for (int i = 0 ; i < 10 ; i++){
            [self doUploadTask:i];
        }
    });
    dispatch_async(queue, ^{
        for (int i = 10 ; i < 20 ; i++){
            [self doUploadTask:i];
        }
    });
    
}

- (void)addTask{
    
}

- (void)doUploadTask:(int)taskNo{
    
    @weakify(self);
    
    BLAsyncBlockOperation *opera = [BLAsyncBlockOperation blockOperationWithBlock:^(BLAsyncBlockOperation * _Nonnull asyncOperation) {
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            @strongify(self);
            if (!self || asyncOperation.isCancelled) {
                return;
            }
            
            NSLog(@"【任务】开始 %d",taskNo);
            
            [NSThread sleepForTimeInterval:1];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                
                [asyncOperation complete];
                
                NSLog(@"【任务】结束 %d | 一共: %@ 任务",taskNo,@(self.ongoingQueue.operationCount));
        
            });
        });
    }];
    
    [self.ongoingQueue addOperation:opera];

}

- (void)cancelAllTask{
    [self.ongoingQueue cancelAllOperations];
}

#pragma mark - *********** KVO ***********

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                         change:(NSDictionary *)change context:(void *)context
{
    if (object == self.compressOperQueue && [keyPath isEqualToString:@"operations"] && context == &kQueueOperationsChanged) {
        if ([self.compressOperQueue.operations count] == 0) {
            NSLog(@"queue has completed");
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object
                               change:change context:context];
    }
}

@end
